from abc import ABC, abstractmethod


class Student:

    def __init__(self, name):
        self.__name = name

    def report(self):
        print(f'Student {self.__name} reports!')


class Banner:

    def __init__(self, string):
        self.__string = string

    def a(self, aa):
        print(f'{self.__string} aa {aa}')

    def a(self, aa):  # overwrite above???
        print(f'{self.__string} bb {aa}')

    @property
    def string(self):
        return self.__string

    @string.setter
    def string(self, string):
        self.__string = string

    def show_with_paren(self):
        print(f'({self.__string})')

    def show_with_aster(self):
        print(f'*{self.__string}*')


class Print(ABC):
    """

    https://stackoverflow.com/questions/2124190/how-do-i-implement-interfaces-in-python

    """

    @abstractmethod
    def print_weak(self):
        pass

    def print_strong(self):
        pass


# class PrintBanner(Banner, Student, Print, ):
class PrintBanner(Print, Banner, Student, ):

    def __init__(self, string):
        """
        https://stackoverflow.com/questions/14206015/pythons-multiple-inheritance-picking-which-super-to-call

        That's not what super() is for. Super basically picks one (or all) of its parents in a specific order.

        :param string:
        """
        # super(PrintBanner, self).__init__(string)
        Banner.__init__(self, string)
        Student.__init__(self, string)

    def print_weak(self):
        self.show_with_paren()

    def print_strong(self):
        self.show_with_aster()


if __name__ == '__main__':

    print(PrintBanner.__mro__)
    obj = PrintBanner('Hello')
    obj.print_weak()
    obj.print_strong()
    obj.report()

    obj.string = 'World'
    obj.print_weak()
    obj.print_strong()
    obj.report()
    print(f'obj.string = {obj.string}')

    obj.a('aa')
